package cm.example.shoppingplatformspringboot.utils;

import cm.example.shoppingplatformspringboot.entity.Manager;
import cm.example.shoppingplatformspringboot.entity.User;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.jetbrains.annotations.NotNull;

import java.util.Date;
import java.util.Map;

/**
 * JWT 工具类，用于生成 JSON Web Token（JWT）令牌。
 * 提供了针对普通用户和管理员两种不同身份的令牌生成方法，以便在应用程序中进行身份验证和授权。
 *
 * <p>JWT 令牌包含以下几部分：
 * <ul>
 * <li>Header（头部）：包含令牌类型和签名算法。</li>
 * <li>Payload（载荷）：包含用户信息和自定义声明。</li>
 * <li>Signature（签名）：用于验证令牌的完整性和防止伪造。</li>
 * </ul>
 *
 * <p>本工具类使用 HMAC256 算法进行签名，凭借配置的密钥来确保令牌的安全性。
 * 令牌的有效期默认设置为 24 小时，之后需要重新生成。
 *
 * @see JWT
 * @see Algorithm
 */
public class JwtUtil {

    // 密钥和有效期常量在工具类中私有化，防止外部直接访问修改
    private static final String SECRET_KEY = "your_secret_key"; // 自定义密钥
    private static final long EXPIRATION_TIME = 1000 * 60 * 60 * 24; // 设置有效期为 24 小时

    /**
     * 为普通用户生成 JWT 令牌。
     *
     * <p>该方法使用用户账号作为令牌的主题，并包含用户的电话号码作为声明信息。
     * 令牌带有当前时间的签发时间戳以及过期时间戳，过期时间基于预设的有效期计算得出。
     *
     * @param user 普通用户对象，包含账号和电话信息，用于填充令牌内容
     * @return 生成的 JWT 令牌字符串
     * @throws IllegalArgumentException 如果用户对象或其关键信息（账号、电话）为 null 或空字符串
     */
    public static String generateToken(@NotNull User user) {
        return JWT.create()
                .withSubject(user.getAccount())  // 存储手机号作为 JWT 的主体
                .withClaim("telphone", user.getTelphone())
                .withIssuedAt(new Date())  // 当前时间
                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))  // 设置有效期
                .sign(Algorithm.HMAC256(SECRET_KEY));  // 使用 HMAC256 算法加密
    }

    /**
     * 为管理员生成 JWT 令牌。
     *
     * <p>与普通用户令牌类似，该方法使用管理员账号作为令牌主题，并包含最后登录 IP 地址作为声明信息。
     * 同样带有签发时间和过期时间，遵循相同的有效期规则。
     *
     * @param manager 管理员对象，包含账号和最后登录 IP 信息，用于填充令牌内容
     * @return 生成的 JWT 令牌字符串
     * @throws IllegalArgumentException 如果管理员对象或其关键信息（账号、最后登录 IP）为 null 或空字符串
     */
    public static String generateAdminToken(@NotNull Manager manager) {
        return JWT.create()
                .withSubject(manager.getAccount())
                .withClaim("last_login_ip", manager.getLast_login_ip())
                .withIssuedAt(new Date())  // 当前时间
                .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))  // 设置有效期
                .sign(Algorithm.HMAC256(SECRET_KEY));  // 使用 HMAC256 算法加密
    }

    // 💡 添加校验方法
    public static DecodedJWT verifyToken(String token) {
        return JWT.require(Algorithm.HMAC256(SECRET_KEY))
                .build()
                .verify(token);
    }

    // 💡 添加解析方法
    public static Map<String, Claim> parseToken(String token) {
        return verifyToken(token).getClaims();
    }
}